\section{DMU}
\subsection{Object}
若干数据块被DMU组织为一个对象（{\em object}），
例如POSIX文件对象（类型为\,\verb|DMU_OT_PLAIN_FILE_CONTENTS|）和%
POSIX目录对象（类型为\,\verb|DMU_OT_DIRECTORY_CONTENTS|）。
每个对象由一个对应\,\verb|dnode_phys_t|结构（简称{\em dnode}）表示，
该结构描述了哪些数据块如何被组织为这个对象，
譬如，文件对象描述了该文件所有数据块在磁盘中的分布；
又如，目录对象负责如何在该目录下进行文件名检索。
粗略地，
可以把\,\verb|dnode_phys_t|看作一个模版，
各种类型的对象是这个模版的不同实例。
\verb|dnode_phys_t|是一个512字节的结构，
定义如代码段\,\ref{src:dnode}\,所示。
\inputclisting{src/dnode.h}
              {ZFS对象}{dnode}

\subsubsection{间接寻址}
如代码段\,\ref{src:dnode}\,所示，
一个对象仅含有一个块指针，
最大可以描述的数据即ZFS支持的最大块尺寸128K。
当数据大于这个尺寸就需要通过中介块，
即间接寻址方式来完成数据在磁盘上的定位，
即对象的\verb|blk_ptr|域是该对象描述的数据块树的根。
ZFS支持最深达6级的间接寻址，
第一级间接块的尺寸为16K，
容纳$2^7$个块指针，
之后的每一级可以采用最大128K的间接块，
于是一个对象可以描述的最大数据为$2^{7 + 10 \times 4 + 17} = 2^{64}$字节。
图\,\ref{fig:dn_ind}\,演示了一个三级间接寻址。
\begin{figure}[ht]
  \centering
  \includegraphics[width=\textwidth]{dn_ind.pdf}
  \caption{间接寻址}\label{fig:dn_ind}
\end{figure}

\subsection{Object Set}
DMU这一层也负责把多个对象组织为一个对象集（{\em Object Set}），
例如文件系统（类型为\verb|DMU_OST_ZFS|）。
对象集物理地存储为磁盘块中的dnode数组，
并由\verb|objset_phys_t|描述。

\inputclisting{src/objset.h}
              {ZFS对象集}{objset}

\verb|objset_phys_t|结构定义如代码段\,\ref{src:objset}\,所示。
\verb|os_type|域表明此对象集类型，
ZFS共支持三种对象集，
\verb|DMU_OST_META|、
\verb|DMU_OST_ZFS|、
及\verb|DMU_OST_ZVOL|。
\verb|os_meta_dnode|用于描述此对象集中的所有dnode，
其对象类型为\verb|DMU_OT_DNODE|，
表明该对象描述的所有数据块存储的数据为dnode对象。

\begin{figure}[!hb]
  \centering
  \includegraphics{objset.pdf}
  \caption{对象集内部组织结构}\label{fig:objset_ind}
\end{figure}

一个dnode占用512字节，
一个最大尺寸的块仅能容纳256个dnode，
当需要分配更多dnode就必须采用间接寻址。
根据之前关于间接寻址的介绍可知，
一个对象集最多可以有$2^{7 + 10 \times 4 + 8} = 2^{55}$个对象。
图\,\ref{fig:objset_ind}\,示例一个由对象集至对象的一级间接寻址。

每个对象在对象集内有一个唯一的对象号作为其在dnode数组中的索引。
对象号为1，
即dnode数组中第二个元素固定用作特殊用途，
例如文件系统对象集dnode数组的第二个元素用于描述该文件系统根目录，
它记录诸如根目录对象在dnode数组中的索引（图\,\ref{fig:objset_ind}\,中为3）。
